/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef RELATIONAL_STORE_H
#define RELATIONAL_STORE_H

/**
 * @addtogroup RDB
 * @{
 *
 * @brief The relational database (RDB) store manages data based on relational models.
 * A complete set of mechanisms for managing local databases is provided based on the underlying SQLite.
 * To satisfy different needs in complicated scenarios, the RDB module provides a series of methods for performing
 * operations such as adding, deleting, modifying, and querying data, and supports direct execution of SQL statements.
 *
 * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core
 * @since 10
 */


/**
 * @file relational_store.h
 *
 * @brief Provides APIs for managing RDB stores.
 * File to include: <database/rdb/relational_store.h>
 * @library libnative_rdb_ndk.z.so
 * @since 10
 */

#include "oh_cursor.h"
#include "oh_predicates.h"
#include "oh_value_object.h"
#include "oh_values_bucket.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Enumerates the RDB store security levels.
 *
 * @since 10
 */
typedef enum OH_Rdb_SecurityLevel {
    /**
     * Low security level.
     *
     * If data leakage occurs, minor impact will be caused.
     */
    S1 = 1,
    /**
     * Medium security level.
     *
     * If data leakage occurs, moderate impact will be caused.
     */
    S2,
    /**
     * High security level.
     *
     If data leakage occurs, major impact will be caused.
     */
    S3,
    /**
     * Critical security level.
     *
     * If data leakage occurs, critical impact will be caused.
     */
    S4
} OH_Rdb_SecurityLevel;

/**
 * @brief Enumerates the encryption levels of the database directories.
 *
 * @since 11
 */
typedef enum Rdb_SecurityArea {
    /**
     * Encryption level 1.
     */
    RDB_SECURITY_AREA_EL1 = 1,
    /**
     * Encryption level 2.
     */
    RDB_SECURITY_AREA_EL2,
    /**
     * Encryption level 3.
     */
    RDB_SECURITY_AREA_EL3,
    /**
     * Encryption level 4.
     */
    RDB_SECURITY_AREA_EL4,
} Rdb_SecurityArea;

/**
 * @brief Defines the RDB store configuration.
 *
 * @since 10
 */
#pragma pack(1)
typedef struct {
    /** Size of the struct. */
    int selfSize;
    /** Path of the database file. */
    const char *dataBaseDir;
    /** RDB store name. */
    const char *storeName;
    /** Application bundle name. */
    const char *bundleName;
    /** Module name. */
    const char *moduleName;
    /** Whether to encrypt the RDB store. */
    bool isEncrypt;
    /** Security level of the RDB store. For details, see {@link OH_Rdb_SecurityLevel}. */
    int securityLevel;
    /**
     * Encryption level of the database directory. For details, see {@link Rdb_SecurityArea}.
     *
     * @since 11
     */
    int area;
} OH_Rdb_Config;
#pragma pack()

/**
 * @brief Defines the RDB store type.
 *
 * @since 10
 */
typedef struct {
    /** Unique identifier of an OH_Rdb_Store instance. */
    int64_t id;
} OH_Rdb_Store;

/**
 * @brief Represents the configuration of an RDB store. Different from {@link OH_Rdb_Config},
 * this struct does not have its member variables exposed externally. Methods are used to configure its properties.
 *
 * @since 14
 */
typedef struct OH_Rdb_ConfigV2 OH_Rdb_ConfigV2;

/**
 * @brief Enumerates the database kernel types.
 *
 * @since 14
 */
typedef enum Rdb_DBType {
    /**
     * @brief SQLite is used as the database kernel.
     */
    RDB_SQLITE = 1,
    /**
     * @brief Cayley is used as the database kernel.
     */
    RDB_CAYLEY = 2,
    /**
     * @brief Maximum value of the database kernel type, which is an invalid value.
     */
    DBTYPE_BUTT = 64,
} Rdb_DBType;

/**
 * @brief Creates an {@link OH_Rdb_ConfigV2} instance.
 *
 * @return Returns the pointer to the {@link OH_Rdb_ConfigV2} instance created.
 * @see OH_Rdb_ConfigV2
 * @since 14
 */
OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig();

/**
 * @brief Destroys an {@link OH_Rdb_ConfigV2} instance created by {@link OH_Rdb_CreateConfig}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance to destroy.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config);

/**
 * @brief Sets the database file path for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param dataBaseDir Pointer to the database file path to set. The full path, including the database name,
 * cannot exceed a maximum of 1024 characters.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 *config, const char *databaseDir);

/**
 * @brief Sets the RDB store name for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param storeName Pointer to the RDB store name to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName);

/**
 * @brief Sets the bundle name for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param bundleName Pointer to the bundle name to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName);

/**
 * @brief Sets the application module name for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param moduleName Pointer to the module name to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName);

/**
 * @brief Sets whether to encrypt the RDB store for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param isEncrypted Whether to encrypt the RDB store. The value <b>true</b> means to encrypt the RDB store;
 * the value <b>false</b> means the opposite.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 *config, bool isEncrypted);

/**
 * @brief Sets the {@link OH_Rdb_SecurityLevel} for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param securityLevel RDB store security level {@link OH_Rdb_SecurityLevel} to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel);

/**
 * @brief Sets the encryption level {@link Rdb_SecurityArea} for the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param area Encryption level {@link Rdb_SecurityArea} of the RDB store directory to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area);

/**
 * @brief Sets the database type {@link Rdb_DBType} for the given {@link OH_Rdb_ConfigV2}.
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param dbType Database type {@link Rdb_DBType} to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * <b>RDB_E_NOT_SUPPORTED</b indicates that the current operation is not supported.
 * @since 14
 */
int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType);

/**
 * @brief Obtains the supported database types {@link Rdb_DBType}.
 * @param typeCount Pointer to the length of the array of the supported database types obtained.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 14
 */
const int *OH_Rdb_GetSupportedDbType(int *typeCount);

/**
 * @brief Creates an {@link OH_VObject} instance.
 *
 * @return Returns the pointer to the {@link OH_VObject} instance created if the operation is successful;
 * returns NULL otherwise.
 * @see OH_VObject.
 * @since 10
 */
OH_VObject *OH_Rdb_CreateValueObject(void);

/**
 * @brief Creates an {@link OH_VBucket} instance.
 *
 * @return Returns the pointer to the {@link OH_VBucket} instance created if the operation is successful;
 * returns NULL otherwise.
 * @see OH_VBucket.
 * @since 10
 */
OH_VBucket *OH_Rdb_CreateValuesBucket(void);

/**
 * @brief Creates an {@link OH_Predicates} instance.
 *
 * @param table Pointer to the name of the database table.
 * @return Returns the pointer to the {@link OH_Predicates} instance created if the operation is successful;
 * returns NULL otherwise.
 * @see OH_Predicates.
 * @since 10
 */
OH_Predicates *OH_Rdb_CreatePredicates(const char *table);

/**
 * @brief Obtains or opens an {@link OH_Rdb_Store} instance for RDB store operations.
 *
 * @param config Pointer to the {@link OH_Rdb_Config} instance, which is the configuration of the RDB store.
 * @param errCode Pointer to the operation result.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @return Returns the pointer to the {@link OH_Rdb_Store} instance obtained if the operation is successful;
 * returns NULL otherwise.
 * @see OH_Rdb_Config, OH_Rdb_Store.
 * @since 10
 */
OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode);

/**
 * @brief Creates or opens an {@link OH_Rdb_Store} instance from the given {@link OH_Rdb_ConfigV2}.
 *
 * @param config Pointer to the {@link OH_Rdb_ConfigV2} instance, which is the configuration of the RDB store.
 * @param errCode Pointer to the operation result.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @return Returns the pointer to the {@link OH_Rdb_Store} instance created if the operation is successful;
 * returns NULL otherwise.
 * @see OH_Rdb_ConfigV2, OH_Rdb_Store.
 * @since 14
 */
OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode);

/**
 * @brief Destroys an {@link OH_Rdb_Store} instance to reclaim the memory occupied.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance to destroy.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_CloseStore(OH_Rdb_Store *store);

/**
 * @brief Deletes an RDB store.
 *
 * @param config Pointer to the configuration of the RDB store to delete.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @since 10
 */
int OH_Rdb_DeleteStore(const OH_Rdb_Config *config);

/**
 * @brief Deletes an RDB store based on the given {@link OH_Rdb_ConfigV2}.
 * If a vector database is used, ensure that the vector database has been correctly closed before calling the API.
 *
 * @param config Pointer to the configuration of the RDB store to delete.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_ErrCode.
 * @since 14
 */
int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config);

/**
 * @brief Inserts a row of data into a table.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param table Pointer to the name of the target table.
 * @param valuesBucket Pointer to the data {@link OH_VBucket} to insert.
 * @return Returns <b>rowID</b> if the operation is successful; returns an error code otherwise.
 *     {@link RDB_ERR} indicates the operation fails.
 *     {@link RDB_E_INVALID_ARGS} indicates invalid parameters are detected.
 * @see OH_Rdb_Store, OH_VBucket.
 * @since 10
 */
int OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket);

/**
 * @brief Updates data in an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param valuesBucket Pointer to the data {@link OH_VBucket} to be written to the table.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the update conditions.
 * @return Returns the number of updated rows if the operation is successful;
 * returns an error code otherwise.
 *     {@link RDB_ERR} indicates the data update fails.
 *     {@link RDB_E_INVALID_ARGS} indicates invalid parameters are detected.
 * @see OH_Rdb_Store, OH_Bucket, OH_Predicates.
 * @since 10
 */
int OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates);

/**
 * @brief Deletes data from an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the deletion conditions.
 * @return Returns the number of deleted rows if the operation is successful;
 * returns an error code otherwise.
 *     {@link RDB_ERR} indicates the data deletion fails.
 *     {@link RDB_E_INVALID_ARGS} indicates invalid parameters are detected.
 * @see OH_Rdb_Store, OH_Predicates.
 * @since 10
 */
int OH_Rdb_Delete(OH_Rdb_Store *store, OH_Predicates *predicates);

/**
 * @brief Queries data in an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the query conditions.
 * @param columnNames Pointer to the columns to be queried. If this parameter is not specified,
 * the query applies to all columns.
 * @param length Length of the <b>columnNames</b> array. If <b>length</b> is greater than the length of
 * <b>columnNames</b> array, out-of-bounds access occurs.
 * @return Returns the pointer to the {@link OH_Cursor} instance if the operation is successful; returns NULL otherwise.
 * @see OH_Rdb_Store, OH_Predicates, OH_Cursor.
 * @since 10
 */
OH_Cursor *OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length);

/**
 * @brief Executes an SQL statement that contains specified arguments but returns no value.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param sql Pointer to the SQL statement to execute.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql);

/**
 * @brief Executes an SQL statement that returns no value based on the specified transaction ID.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param trxId Transaction ID obtained by calling {@link OH_Rdb_BeginTransWithTrxId}. When the value is set
 * to <b>0</b>, the transaction is not enabled.
 * @param sql Pointer to the SQL statement to execute.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b> indicates invalid parameters. The possible causes are as follows:
 *      The input parameter is a null pointer.
 *      The current transaction ID is not obtained by {@link OH_Rdb_BeginTransWithTrxId}.
 *      The current transaction ID has been committed by {@link OH_Rdb_CommitByTrxId}.
 *      The transaction of the specified ID has been rolled back by {@link OH_Rdb_RollBackByTrxId}.
 *      <b>store</b> or <b>sql</b> is NULL.
 * <b>RDB_E_NOT_SUPPORTED</b indicates that the current operation is not supported.
 * @see OH_Rdb_Store.
 * @since 14
 */
int OH_Rdb_ExecuteByTrxId(OH_Rdb_Store *store, int64_t trxId, const char *sql);

/**
 * @brief Executes an SQL statement to query data in an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param sql Pointer to the SQL statement to execute.
 * @return Returns the pointer to the {@link OH_Cursor} instance if the operation is successful; returns NULL otherwise.
 * @see OH_Rdb_Store.
 * @since 10
 */
OH_Cursor *OH_Rdb_ExecuteQuery(OH_Rdb_Store *store, const char *sql);

/**
 * @brief Begins the transaction before executing an SQL statement.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_BeginTransaction(OH_Rdb_Store *store);

/**
 * @brief Rolls back the SQL statements executed.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_RollBack(OH_Rdb_Store *store);

/**
 * @brief Commits the SQL statements executed.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_Commit(OH_Rdb_Store *store);

/**
 * @brief Begins a transaction and obtains the transaction ID before executing an SQL statement.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param trxId Pointer to the transaction ID obtained.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * <b>RDB_E_NOT_SUPPORTED</b indicates that the current operation is not supported.
 * @see OH_Rdb_Store.
 * @since 14
 */
int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId);

/**
 * @brief Rolls back the executed SQL statement based on the specified transaction ID.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param trxId ID of the transaction to roll back.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b> indicates invalid parameters. The possible causes are as follows:
 *      The input parameter is a null pointer.
 *      The current transaction ID is not obtained by {@link OH_Rdb_BeginTransWithTrxId}.
 *      The current transaction ID has been committed by {@link OH_Rdb_CommitByTrxId}.
 *      The transaction of the specified ID has been rolled back by {@link OH_Rdb_RollBackByTrxId}.
 * <b>RDB_E_NOT_SUPPORTED</b indicates that the current operation is not supported.
 * @see OH_Rdb_Store.
 * @since 14
 */
int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId);

/**
 * @brief Commits the executed SQL statement based on the specified transaction ID.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param trxId ID of the transaction to commit.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b> indicates invalid parameters. The possible causes are as follows:
 *      The input parameter is a null pointer.
 *      The current transaction ID is not obtained by {@link OH_Rdb_BeginTransWithTrxId}.
 *      The current transaction ID has been committed by {@link OH_Rdb_CommitByTrxId}.
 *      The transaction of the specified ID has been rolled back by {@link OH_Rdb_RollBackByTrxId}.
 * <b>RDB_E_NOT_SUPPORTED</b indicates that the current operation is not supported.
 * @see OH_Rdb_Store.
 * @since 14
 */
int OH_Rdb_CommitByTrxId(OH_Rdb_Store *store, int64_t trxId);

/**
 * @brief Backs up an RDB store in the specified directory.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param databasePath Pointer to the path of the backup file used to restore the RDB store.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_Backup(OH_Rdb_Store *store, const char *databasePath);

/**
 * @brief Restores an RDB store from the specified database backup file.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param databasePath Pointer to the path of the backup file used to restore the RDB store.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_Restore(OH_Rdb_Store *store, const char *databasePath);

/**
 * @brief Obtains the RDB store version.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param version Pointer to the RDB version obtained.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_GetVersion(OH_Rdb_Store *store, int *version);

/**
 * @brief Sets the RDB store version.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param version Version to set.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 10
 */
int OH_Rdb_SetVersion(OH_Rdb_Store *store, int version);

/**
 * @brief Enumerates the distributed table types.
 *
 * @since 11
 */
typedef enum Rdb_DistributedType {
    /** Distributed database table synced between a device and the cloud. */
    RDB_DISTRIBUTED_CLOUD
} Rdb_DistributedType;

/**
 * @brief Represents the version of {@link Rdb_DistributedConfig}.
 *
 * @since 11
 */
#define DISTRIBUTED_CONFIG_VERSION 1

/**
 * @brief Represents the distributed configuration of a table.
 *
 * @since 11
 */
typedef struct Rdb_DistributedConfig {
    /** Version of <b>Rdb_DistributedConfig</b>. */
    int version;
    /** Whether the table supports auto sync. */
    bool isAutoSync;
} Rdb_DistributedConfig;

/**
 * @brief Sets distributed database tables.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param tables Pointer to the names of the distributed database tables to set.
 * @param count Number of distributed database tables to be set.
 * @param type Distributed type of the table. For details, see {@link Rdb_DistributedType}.
 * @param config Pointer to the configuration of the distributed tables. For details, see {@link Rdb_DistributedConfig}.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 11
 */
int OH_Rdb_SetDistributedTables(OH_Rdb_Store *store, const char *tables[], uint32_t count, Rdb_DistributedType type,
    const Rdb_DistributedConfig *config);

/**
 * @brief Obtains the last modification time of a table in an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param tableName Pointer to the name of the distributed database table.
 * @param columnName Pointer to the column name of the database table.
 * @param values Pointer to the primary keys. If the database table has no primary key,
 * <b>rowid</b> must be passed in through <b>columnName</b>. In this case, <b>values</b> specifies the row numbers of
 * the database table to query.
 * @return Returns the pointer to the {@link OH_Rdb_Store} instance if the operation is successful;
 * returns NULL otherwise.
 * @see OH_Rdb_Store.
 * @since 11
 */
OH_Cursor *OH_Rdb_FindModifyTime(OH_Rdb_Store *store, const char *tableName, const char *columnName,
    OH_VObject *values);

/**
 * @brief Enumerates the data change types.
 *
 * @since 11
 */
typedef enum Rdb_ChangeType {
    /** Data change. */
    RDB_DATA_CHANGE,
    /** Asset change. */
    RDB_ASSET_CHANGE
} Rdb_ChangeType;

/**
 * @brief Represents information about the primary key or row number of the row that changes.
 *
 * @since 11
 */
typedef struct Rdb_KeyInfo {
    /** Number of primary keys or rows with data changed. */
    int count;
    /** Primary key type {@link OH_ColumnType}. */
    int type;
    /**
     * @brief Type of the data changed.
     *
     * @since 11
     */
    union Rdb_KeyData {
        /** Data of the uint64_t type. */
        uint64_t integer;
        /** Data of the double type. */
        double real;
        /** Data of the char \* type. */
        const char *text;
    } *data;
} Rdb_KeyInfo;

/**
 * @brief Represents the version of {@link Rdb_ChangeInfo}.
 *
 * @since 11
 */
#define DISTRIBUTED_CHANGE_INFO_VERSION 1

/**
 * @brief Represents details about the device-cloud sync.
 *
 * @since 11
 */
typedef struct Rdb_ChangeInfo {
    /** Version of <b>Rdb_DistributedConfig</b>. */
    int version;
    /** Name of the table with data changes. */
    const char *tableName;
    /** Type of the data changed, which can be data or asset. */
    int ChangeType;
    /**
    * Location where data is inserted. If the primary key of the table is of the string type, the value
    * is the primary key. Otherwise, the value is the row number of the inserted data.
    */
    Rdb_KeyInfo inserted;
    /**
    * Location where data is updated. If the primary key of the table is of the string type, the value is the
    * primary key. Otherwise, the value is the row number of the updated data.
    */
    Rdb_KeyInfo updated;
    /**
    * Location where data is deleted. If the primary key of the table is of the string type, the value is the
    * primary key. Otherwise, the value is the row number of the deleted data.
    */
    Rdb_KeyInfo deleted;
} Rdb_ChangeInfo;

/**
 * @brief Enumerates the subscription types.
 *
 * @since 11
 */
typedef enum Rdb_SubscribeType {
    /** Subscribe to cloud data changes. */
    RDB_SUBSCRIBE_TYPE_CLOUD,
    /** Subscribe to details of the cloud data change. */
    RDB_SUBSCRIBE_TYPE_CLOUD_DETAILS,
    /**
     * Subscribe to details of the local data change.
     * @since 12
     */
    RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS,
} Rdb_SubscribeType;

/**
 * @brief Defines a callback used to observe the device-cloud data changes.
 *
 * @param context Pointer to the context of the data observer.
 * @param values Pointer to the accounts whose data change is observed.
 * @param count Number of accounts.
 * @since 11
 */
typedef void (*Rdb_BriefObserver)(void *context, const char *values[], uint32_t count);

/**
 * @brief Defines a callback used to observe the details about the device-cloud data change.
 *
 * @param context Pointer to the context of the data observer.
 * @param changeInfo Pointer to {@link Rdb_ChangeInfo}.
 * @param count Number of tables changed.
 * @see Rdb_ChangeInfo.
 * @since 11
 */
typedef void (*Rdb_DetailsObserver)(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count);

/**
 * @brief Defines the callbacks.
 *
 * @since 11
 */
typedef union Rdb_SubscribeCallback {
    /** Callback used to return the details about the device-cloud data change. */
    Rdb_DetailsObserver detailsObserver;

    /** Callback used to return brief device-cloud data change information. */
    Rdb_BriefObserver briefObserver;
} Rdb_SubscribeCallback;

/**
 * @brief Defines a data observer.
 *
 * @since 11
 */
typedef struct Rdb_DataObserver {
    /** Context of the data observer. */
    void *context;

    /** Callback of the data observer. */
    Rdb_SubscribeCallback callback;
} Rdb_DataObserver;

/**
 * @brief Registers an observer for an RDB store.
 * The registered callback will be called when data in a distributed or local RDB store changes.
*
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param type Subscription type. For details, see {@link Rdb_SubscribeType}. If the value is
 * <b>RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS</b>, the callback is called when the data in the local RDB store changes.
 * @param observer Pointer to the {@link Rdb_DataObserver} to register.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @see Rdb_DataObserver.
 * @since 11
 */
int OH_Rdb_Subscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer);

/**
 * @brief Unregisters an observer for an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param type Subscription type. For details, see {@link Rdb_SubscribeType}.
 * @param observer Pointer to the {@link Rdb_DataObserver} to unregister. If this parameter is <b>nullptr</b>,
 * all observers of this type will be unregistered.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @see Rdb_DataObserver.
 * @since 11
 */
int OH_Rdb_Unsubscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer);

/**
 * @brief Enumerates the data sync modes.
 *
 * @since 11
 */
typedef enum Rdb_SyncMode {
    /** Sync with the data with the latest modification time. */
    RDB_SYNC_MODE_TIME_FIRST,
    /** Sync data from a local device to the cloud. */
    RDB_SYNC_MODE_NATIVE_FIRST,
    /** Sync data from the cloud to a local device. */
    RDB_SYNC_MODE_CLOUD_FIRST
} Rdb_SyncMode;

/**
 * @brief Represents the device-cloud sync statistics of a database table.
 *
 * @since 11
 */
typedef struct Rdb_Statistic {
    /** Total number of rows to be synced between the device and cloud in the database table. */
    int total;
    /** Number of rows that are successfully synced between the device and cloud in the database table. */
    int successful;
    /** Number of rows that failed to be synced between the device and cloud in the database table. */
    int failed;
    /** Number of rows that are not executed for device-cloud sync in the database table. */
    int remained;
} Rdb_Statistic;

/**
 * @brief Represents the statistics of device-cloud upload and download tasks of a database table.
 *
 * @since 11
 */
typedef struct Rdb_TableDetails {
    /** Name of the database table. */
    const char *table;
    /** Statistics of the device-cloud upload tasks. */
    Rdb_Statistic upload;
    /** Statistics of the device-cloud download tasks. */
    Rdb_Statistic download;
} Rdb_TableDetails;

/**
 * Enumerates the device-cloud sync progresses.
 *
 * @since 11
 */
typedef enum Rdb_Progress {
    /** The device-cloud sync starts. */
    RDB_SYNC_BEGIN,
    /** The device-cloud sync is in progress. */
    RDB_SYNC_IN_PROGRESS,
    /** The device-cloud sync is finished. */
    RDB_SYNC_FINISH
} Rdb_Progress;


/**
 * Enumerates the device-cloud sync states.
 *
 * @since 11
 */
typedef enum Rdb_ProgressCode {
    /** The device-cloud sync is successful. */
    RDB_SUCCESS,
    /** An unknown error occurs during the device-cloud sync. */
    RDB_UNKNOWN_ERROR,
    /** A network error occurs during the device-cloud sync. */
    RDB_NETWORK_ERROR,
    /** The cloud is unavailable. */
    RDB_CLOUD_DISABLED,
    /** The device-cloud sync of another device is being performed. */
    RDB_LOCKED_BY_OTHERS,
    /**
    * The number of records or size of the data to be synced exceeds the maximum.
    * The maximum value is configured on the cloud.
    */
    RDB_RECORD_LIMIT_EXCEEDED,
    /** The remaining cloud space is less than the size of the data to be synced. */
    RDB_NO_SPACE_FOR_ASSET
} Rdb_ProgressCode;

/**
 * @brief Represents the version of {@link OH_ProgressDetails}.
 *
 * @since 11
 */
#define DISTRIBUTED_PROGRESS_DETAIL_VERSION 1

/**
 * @brief Represents the statistics of device-cloud upload and download tasks of an RDB store.
 *
 * @since 11
 */
typedef struct Rdb_ProgressDetails {
    /** Version of <b>OH_TableDetails</b>. */
    int version;
    /** Device-cloud sync progress. */
    int schedule;
    /** Device-cloud sync state. */
    int code;
    /** Number of the tables synced between the device and cloud. */
    int32_t tableLength;
} Rdb_ProgressDetails;

/**
 * @brief Obtains the device-cloud sync statistics of a table.
 *
 * @param progress Pointer to the {@link OH_ProgressDetails} instance.
 * @param version Version of {@link Rdb_ProgressDetails}.
 * @return Returns the pointer to {@link Rdb_TableDetails} if the operation is successful; returns NULL otherwise.
 * @see Rdb_ProgressDetails
 * @see Rdb_TableDetails
 * @since 11
 */
Rdb_TableDetails *OH_Rdb_GetTableDetails(Rdb_ProgressDetails *progress, int32_t version);

/**
 * @brief Defines a callback used to return the device-cloud sync progress.
 *
 * @param progressDetails Pointer to the details about the device-cloud sync progress.
 * @see Rdb_ProgressDetails.
 * @since 11
 */
typedef void (*Rdb_ProgressCallback)(void *context, Rdb_ProgressDetails *progressDetails);

/**
 * @brief Defines a callback used to return the device-cloud sync details.
 *
 * @param progressDetails Pointer to the device-cloud sync details.
 * @see OH_Rdb_Store.
 * @since 11
 */
typedef void (*Rdb_SyncCallback)(Rdb_ProgressDetails *progressDetails);

/**
 * @brief Defines an observer for the device-cloud sync progress.
 *
 * @since 11
 */
typedef struct Rdb_ProgressObserver {
    /** Context of the device-cloud sync progress observer. */
    void *context;

    /** Callback used to return the device-cloud sync progress. */
    Rdb_ProgressCallback callback;
} Rdb_ProgressObserver;

/**
 * @brief Performs device-cloud sync.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param mode Sync mode. For details, see {@link Rdb_SyncMode}.
 * @param tables Pointer to the names of the tables to sync.
 * @param count Number of tables to sync. If the value is <b>0</b>, all tables in the RDB store will be synced.
 * @param observer Pointer to {@link Rdb_ProgressObserver}.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @since 11
 */
int OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables, int count,
    const Rdb_ProgressObserver *observer);

/**
 * @brief Subscribes to the auto sync progress of an RDB store.
 * The registered callback will be invoked to return the auto sync progress.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param observer Pointer to {@link Rdb_ProgressObserver} for auto sync progress.
 * This callback is invoked to return the auto sync progress.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @see Rdb_ProgressObserver.
 * @since 11
 **/
int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer);

/**
 * @brief Unsubscribes from the auto sync progress of an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param observer Pointer to {@link Rdb_ProgressObserver} to unregister. If it is a null pointer,
 * all callbacks for the auto sync progress will be unregistered.
 * @return Returns the operation result. If the operation fails, an error code is returned.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store.
 * @see Rdb_ProgressObserver.
 * @since 11
 */
int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer);

/**
 * @brief Locks data in an RDB store based on specified conditions.
 * The locked data will be blocked from the device-cloud sync.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the lock conditions.
 * @return Returns the operation result.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store, OH_Predicates.
 * @since 12
 */
int OH_Rdb_LockRow(OH_Rdb_Store *store, OH_Predicates *predicates);

/**
 * @brief Unlocks data in an RDB store based on the specified conditions.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the unlock conditions.
 * @return Returns the operation result.
 * <b>RDB_OK</b> indicates the operation is successful.
 * <b>RDB_E_INVALID_ARGS</b indicates invalid parameters are detected.
 * @see OH_Rdb_Store, OH_Predicates.
 * @since 12
 */
int OH_Rdb_UnlockRow(OH_Rdb_Store *store, OH_Predicates *predicates);

/**
 * @brief Queries the locked data in an RDB store.
 *
 * @param store Pointer to the {@link OH_Rdb_Store} instance.
 * @param predicates Pointer to the {@link OH_Predicates} instance, which specifies the query conditions.
 * @param columnNames Pointer to the columns to be queried. If this parameter is not specified,
 * the query applies to all columns.
 * @param length Length of the <b>columnNames</b> array. If <b>length</b> is greater than the
 * length of <b>columnNames</b> array, out-of-bounds access occurs.
 * @return Returns the pointer to the {@link OH_Cursor} instance if the operation is successful; returns NULL otherwise.
 * @see OH_Rdb_Store, OH_Predicates, OH_Cursor.
 * @since 12
 */
OH_Cursor *OH_Rdb_QueryLockedRow(
    OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length);

#ifdef __cplusplus
};
#endif

#endif // RELATIONAL_STORE_H
